package com.swak.security;

import java.nio.charset.StandardCharsets;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import com.swak.codec.Base64;
import com.swak.utils.StringUtils;

/**
 * 实现AES 的对称加解密；
 * 
 * @author 618lf
 */
public class AES {

	/**
	 * 设置加密模式
	 */
	public static final String AES = "AES";

	/**
	 * 工作模式：CBC
	 */
	private static final String AES_CBC_PKCS5 = "AES/CBC/PKCS5Padding";

	/**
	 * 工作模式：ECB
	 */
	private static final String AES_ECB_PKCS5 = "AES/ECB/PKCS5Padding";

	static {
		try {
			KeyGenerator.getInstance(AES).init(128);
		} catch (Exception e) {
		}
	}

	/**
	 * 解密
	 * 
	 * @param encrypted  需要解密的内容
	 * @param key 密码
	 * @param iv 向量
	 * @param mode CBC or ECB
	 * @return
	 */
	public static String decrypt(String encrypted, String key, String iv, String mode) {
		byte[] encrypted64 = Base64.decodeBase64(encrypted);
		byte[] key64 = key.getBytes(StandardCharsets.UTF_8);
		byte[] iv64 = iv.getBytes(StandardCharsets.UTF_8);
		try {
			Cipher cipher = Cipher.getInstance("CBC".equals(mode) ? AES_CBC_PKCS5 : AES_ECB_PKCS5);

			// 设置为解密模式
			if ("CBC".equals(mode)) {
				cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key64, AES), new IvParameterSpec(iv64));
			} else {
				cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key64, AES));
			}

			return new String(cipher.doFinal(encrypted64));
		} catch (Exception e) {
			return StringUtils.EMPTY;
		}
	}

	/**
	 * 加密
	 * 
	 * @param content  需要加密的内容
	 * @param key   密码
	 * @param iv   向量
	 * @param mode CBC or ECB
	 * @return
	 */
	public static String ecrypt(String content, String key, String iv, String mode) {
		try {

			// 初始化为加密模式的密码器 - 向量器
			Cipher cipher = Cipher.getInstance("CBC".equals(mode) ? AES_CBC_PKCS5 : AES_ECB_PKCS5);
			if ("CBC".equals(mode)) {
				cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES),
						new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8)));
			} else {
				cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES));
			}

			byte[] bytes = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));

			// 使用base64解码
			return Base64.encodeBase64String(bytes);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
}